package contracts

import (
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"fmt"
	"strings"
	"github.com/ethereum/go-ethereum/common"
	"github.com/OpenBazaar/openbazaar-go/incubator/contracts/utiliy"
	"io/ioutil"

	"github.com/OpenBazaar/openbazaar-go/repo"
	"github.com/OpenBazaar/openbazaar-go/pb"
	"github.com/OpenBazaar/openbazaar-go/core"
	"path"
	"github.com/OpenBazaar/openbazaar-go/incubator/rpc"
)

// Token is an auto generated Go binding around an Ethereum contract.
type Token struct {
	TokenCaller     // Read-only binding to the contract
	TokenTransactor // Write-only binding to the contract
}
// MyTokenCaller is an auto generated read-only Go binding around an Ethereum contract.
type TokenCaller struct {
	contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// MyTokenTransactor is an auto generated write-only Go binding around an Ethereum contract.
type TokenTransactor struct {
	contract *bind.BoundContract // Generic contract wrapper for the low level calls
}

//func NewToken(address common.Address, filename string , backend bind.ContractBackend) (*Token, error) {
//	contract, err := BindToken(address, filename, backend, backend)
//	if err != nil {
//		return nil, err
//	}
//	return &Token{TokenCaller: TokenCaller{contract: contract}, TokenTransactor: TokenTransactor{contract: contract}}, nil
//}

func NewToken(address common.Address, ABI string , backend bind.ContractBackend) (*Token, error) {
	contract, err := BindToken(address, ABI, backend, backend)
	if err != nil {
		return nil, err
	}
	return &Token{TokenCaller: TokenCaller{contract: contract}, TokenTransactor: TokenTransactor{contract: contract}}, nil
}

// bindMyToken binds a generic wrapper to an already deployed contract.
//func BindToken(address common.Address,filename string ,caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
//	parsed := LoadABI(filename)
//	return bind.NewBoundContract(address, parsed, caller, transactor), nil
//}

func BindToken(address common.Address,ABI string ,caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
	parsed := LoadABI(ABI)
	return bind.NewBoundContract(address, parsed, caller, transactor), nil
}

//func LoadABI (filename string)(abi.ABI){
//	var byte ,err1= ioutil.ReadFile(filename)
//	if err1 != nil {
//		fmt.Println("readFile: ", err1.Error())
//	}
//	var MyABI string = string(byte[:])
//	parsed, err := abi.JSON(strings.NewReader(MyABI))
//	if err != nil {
//		fmt.Println("JSONread: ", err1.Error())
//	}
//	return parsed
//}

func LoadABI (ABI string)(abi.ABI){
	parsed, err := abi.JSON(strings.NewReader(ABI))
	if err != nil {
		fmt.Println("JSONread: ", err.Error())
	}
	return parsed
}

func CallContract(contractAddr string, ABIfile string) (*Token, error) {
	client, error := utiliy.Connect(rpc.BlockChainURL)
	if client == nil {
		return nil, error
	}
	token, err := NewToken(common.HexToAddress(contractAddr), ABIfile, client)
	if err != nil {
		return nil, err
	}
	return token, nil
}

func GetAuth(n *core.OpenBazaarNode) (*bind.TransactOpts ,error) {
	var profile pb.Profile
	profile, error3 := n.GetProfile()
	if error3 != nil {
		fmt.Println("Failed to open profile: %v", error3)
		return nil, error3
	}
	repoPath, error4 := repo.GetRepoPath(false)
	key, error4 := ioutil.ReadFile(path.Join(repoPath, "keystore", profile.Keypath))
	if error4 != nil {
		fmt.Println("%s", error4.Error())
	}
	var keydata string = string(key)
	auth, error5 := bind.NewTransactor(strings.NewReader(keydata),profile.Keywords)
	if error5 != nil {
		fmt.Println("%s", error5.Error())
	}
	return auth, nil
}

